import * as vscode from "vscode";
import * as path from "path";
import { showBar } from "./functionMenu";
import { CommandId } from "@ap/command";
import {
  ConfigurationItem,
  ConfigurationKey,
} from "@ap/util/vscode/setInsConfig";
let editor: vscode.TextEditor;
let range: vscode.Range | undefined;
let decorationsOptions: vscode.TextEditorDecorationType | null;
let codeLenses: vscode.CodeLens[] = [];
let command: vscode.Command;
/**
 * ChatjptFunctionProvider类实现了vscode.CodeLensProvider接口，用于在代码编辑器的侧边栏中提供代码透镜功能
 * 该类的主要作用是查找和标识代码中的函数、类、接口等符号，以便用户能够更方便地跳转到这些代码块
 */
export class ChatjptFunctionProvider implements vscode.CodeLensProvider {
  /**
   * 提供代码透镜
   * 该方法通过执行DocumentSymbolProvider来获取文档中的所有符号，然后为每个函数、类、接口等创建一个代码透镜
   *
   * @param document 当前的文本文档
   * @param token 取消操作的标记
   * @returns 返回一个代码透镜数组，包含所有找到的代码透镜
   */
  public async provideCodeLenses(
    document: vscode.TextDocument,
    token: vscode.CancellationToken,
  ): Promise<vscode.CodeLens[]> {
    if (
      !vscode.workspace
        .getConfiguration(ConfigurationItem.CHATJPT_TOOL)
        .get(ConfigurationKey.CHATJPT_SHORTCUT_CODE)
    ) {
      return [];
    }
    const fileName = path.basename(document.fileName);
    if (
      fileName.endsWith("d.ts") ||
      document.uri.fsPath.includes("/dist/") ||
      document.uri.fsPath.includes("/types/")
    ) {
      return [];
    }
    const symbols = await vscode.commands.executeCommand<
      vscode.DocumentSymbol[]
    >("vscode.executeDocumentSymbolProvider", document.uri);

    if (!Array.isArray(symbols)) {
      return [];
    }
    codeLenses = [];
    findSymbol(symbols);
    return codeLenses;
  }
}

/**
 * 高亮代码行函数
 * 该函数用于在编辑器中高亮显示指定范围的代码，并将该代码显示在侧边栏中
 *
 * @param range 需要高亮的代码范围
 */
export function highlightCodeLinesFunction(range: vscode.Range) {
  const editor = vscode.window.activeTextEditor;
  if (editor) {
    editor.selection = new vscode.Selection(
      new vscode.Position(range.start.line, 0),
      new vscode.Position(range.end.line, 9999),
    );
    editor.revealRange(
      range,
      vscode.TextEditorRevealType.InCenterIfOutsideViewport,
    );
    showBar(editor.document.getText(editor.selection));
  }
}

/**
 * 查找符号函数
 * 该函数递归地遍历文档符号，找到函数、类、接口等，并为它们创建代码透镜
 *
 * @param symbols 文档符号数组
 */
function findSymbol(symbols: vscode.DocumentSymbol[]) {
  for (const symbol of symbols) {
    // 如果符号有子符号，则递归查找
    if (symbol.children) {
      findSymbol(symbol.children);
    }
    if (!isShouldCreateCodeLens(symbol.kind)) {
      continue;
    }
    if (
      !vscode.workspace
        .getConfiguration(ConfigurationItem.CHATJPT_TOOL)
        .get(ConfigurationKey.CHATJPT_SHORTCUT_CODE_ANY_FUNCTION)
    ) {
      if (symbol.name.includes("()")) {
        continue;
      }
    }
    createsCodeLens(symbol.range);
  }
}

/*
 * 创建代码透镜函数
 * 该函数为给定的文档符号创建一个代码透镜，透镜上显示特定的图标和标题，并绑定到一个命令
 *
 * @param symbol 文档符号，用于创建代码透镜
 */
function createsCodeLens(range: vscode.Range) {
  command = {
    // 显示的内容
    title: "$(arena-chatjpt-icon)$(arena-down-icon)",
    // 鼠标点击触发的事件
    command: CommandId.chatjpt_fastFunction,
    // 事件的参数
    arguments: [range],
  };
  // 注册进入codelen
  codeLenses.push(new vscode.CodeLens(range, command));
}

function isShouldCreateCodeLens(kind: vscode.SymbolKind) {
  return vscode.workspace
    .getConfiguration(ConfigurationItem.CHATJPT_TOOL)
    .get(getConfigurationKeyForSymbolKind(kind));
}
function getConfigurationKeyForSymbolKind(kind: vscode.SymbolKind) {
  switch (kind) {
    case vscode.SymbolKind.Class:
      return ConfigurationKey.CHATJPT_SHORTCUT_CODE_CLASS;
    case vscode.SymbolKind.Constructor:
      return ConfigurationKey.CHATJPT_SHORTCUT_CODE_CONSTRUCTOR;
    case vscode.SymbolKind.Enum:
      return ConfigurationKey.CHATJPT_SHORTCUT_CODE_ENUM;
    case vscode.SymbolKind.Interface:
      return ConfigurationKey.CHATJPT_SHORTCUT_CODE_INTERFACE;
    case vscode.SymbolKind.Method:
      return ConfigurationKey.CHATJPT_SHORTCUT_CODE_METHOD;
    case vscode.SymbolKind.Module:
      return ConfigurationKey.CHATJPT_SHORTCUT_CODE_MODULE;
    case vscode.SymbolKind.Namespace:
      return ConfigurationKey.CHATJPT_SHORTCUT_CODE_NAMESPACE;
    case vscode.SymbolKind.Variable:
      return ConfigurationKey.CHATJPT_SHORTCUT_CODE_VARIABLE;
    case vscode.SymbolKind.Function:
      return ConfigurationKey.CHATJPT_SHORTCUT_CODE_FUNCTION;
    default:
      return "";
  }
}
